/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 *
 * @author Dustin
 */
public class Server extends Thread implements SMTP {

    public final static String SERVER_NAME = "smtp.saxion.com ESMTP saxion123";
    public final static String WELCOME = "Welcome";
    public final static int DEFAULT_PORT = 587;

    public int state = DISCONNECTED;
    private boolean connected;
    private boolean running = true;
    private ServerSocket serverSocket;
    private BufferedReader bufIn;
    private BufferedWriter bufOut;

    public Server() {
        try {
            serverSocket = new ServerSocket(DEFAULT_PORT);
            start();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void run() {
        while(running) {
            if(!connected) {
                try {
                    Socket s = serverSocket.accept();
                    bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
                    bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
                    command(CONNECT + " " + SERVER_NAME);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } else {
                try {
                    String readLine;
                    while(running && (readLine = bufIn.readLine()) != null) {
                        command(readLine);
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                } 
            }
        }
    }

    public boolean isConnected() {
        return connected;
    }

    public boolean isRunning() {
        return running;
    }

    public void disconnect() {
        if(connected) {
            try {
                connected = false;
                running = false;
                serverSocket.close();
                bufIn.close();
                bufOut.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * Command to write the given String out.
     * @param message the String to be written out
     */
    private void sendMessage(String message) {
        if(connected) {
            try {
                bufOut.write(message + CRLF);
                bufOut.flush();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    public void command(String message) {
        System.out.println(message);
        String[] messageArray = message.split(" ");
        if(state == DISCONNECTED && messageArray[0].toUpperCase().equals(CONNECT)) {
            connected = true;
            state = CONNECTED;
            sendMessage("220 " + SERVER_NAME);
        } else if(messageArray[0].toUpperCase().equals(QUIT)) {
            sendMessage("221 closing connection");
            sendMessage(DISCONNECT);
            disconnect();
            state = DISCONNECTED;
        } else if(messageArray[0].toUpperCase().equals(HELLO)) {
            if(state == CONNECTED) {
                state = CONTACT;
                sendMessage("250 " + WELCOME + " " + (messageArray.length > 1 ? messageArray[1] : ""));
            }
        } else if(message.toUpperCase().startsWith(MAIL)) {
            if(state == CONTACT) {
                state = MAILFROM;
                sendMessage("250 OK.");
            } else if(state == CONNECTED || state == CONTACT) {
                sendMessage("503 HELO first.");
            }
        } else if(message.toUpperCase().startsWith(RECIPIENT)) {
            if(state == MAILFROM) {
                state = MAILTO;
                sendMessage("250 OK.");
            }  else if(state == CONNECTED || state == CONTACT) {
                sendMessage("503 HELO first.");
            }
        } else if(state == MAILDATA) {
                if(messageArray[0].toUpperCase().equals(".") && messageArray.length == 1) {
                    state = SEND;
                    sendMessage("250 Ok: queued as -1");
                }  else if(state == CONNECTED || state == CONTACT) {
                    sendMessage("503 HELO first.");
                }
        } else if(messageArray[0].toUpperCase().equals(DATA)) {
            if(state == MAILTO) {
                state = MAILDATA;
                sendMessage("354 End data with <CR><LF>.<CR><LF>");
            }  else if(state == CONNECTED || state == CONTACT) {
                sendMessage("503 HELO first.");
            }
        } else if(state == SEND) {
            state = CONTACT;
        } else {
            sendMessage("502 Unrecognized command.");
        }
    }
}
